package 
{
	import laya.d3.core.light.DirectionLight;
	import laya.d3.core.scene.Scene;
	import laya.utils.Handler;
	import laya.d3.math.Vector3;
	import laya.d3.core.Sprite3D;
	import laya.d3.core.MeshSprite3D;
	import laya.renders.Render;
	import laya.utils.Browser;
	import laya.events.Event;
	import laya.debug.tools.TimerControlTool;
	import laya.d3.utils.Physics;
	import laya.d3.math.Ray;
	import laya.d3.component.physics.MeshCollider;
	import laya.d3.component.physics.BoxCollider;
	import laya.d3.math.BoundBox;
	import laya.d3.utils.RaycastHit;
	import laya.d3.core.Layer;
	import laya.d3.core.PhasorSpriter3D;
	import laya.d3.math.Vector4;
	import laya.webgl.WebGLContext;
	import view.GameView;
	import view.GameSetting;
	import view.GameOverView;

	/**
	 * ...
	 * @author
	 */
	public class GameManager{
		private static var instance:GameManager;

		private var camera:GameCamera;
		private var scene:GameScene;
		private var player:Player;

		private var CANNON:Object = Browser.window.CANNON;

		public static const stageWidth:int = 1280;
		public static const stageHeight:int = 720;

		private var world:*;
		private var fixedTimeStep:Number = 1.0 / 60.0;
		private var maxSubSteps:int = 3;
		private var lastTime:Number = 0;

		/*-----------游戏参数-----------*/
		//最大飞行距离
		public var MAX_DIS:Number = 300;
		//弓箭飞行最大速度
		public static var speed:Number = 50;
		//拉弓动作最大时长(ms)
		public static var drawTime:Number = 417;
		//摇杆灵敏度
		public static var CAMERA_ROTATION_SPEED:Number = 0.000015;
		public static var CAMERA_ROTATION_SPEED_MIN:Number = 0.000005;
		public static var CAMERA_ROTATION_SPEED_MAX:Number = 0.000025;
		public static var MAX_TARGET_NUM:int = 30;
		//目标移动类型随机概率
		public var randomMoveArr:Array = [80,100];
		//是否使用陀螺仪
		public static var useGyroscope:Boolean = true;
		public var refreshRadius:int = 50;
		/*-----------游戏参数-----------*/
		
		private var curTime:int;
		private var arrowList:Array;
		private var targetList:Array;
		private var ray:Ray = new Ray(new Vector3(0, 0, 0), new Vector3(0, 0, 0));
		private var outHitInfo:RaycastHit = new RaycastHit();
		private var phasorSpriter3D:PhasorSpriter3D = new PhasorSpriter3D();
		private var _color:Vector4 = new Vector4(1, 0, 0, 1);
		private var _linePos:Vector3 = new Vector3(0, 0, 0);
		//碰撞检测指定层级
		private var layerNum:int = 10;
		private var randomTime:int;
		private var randomCount:int;
		private var refreshMaxTime:int = 3;
		private var refreshMinTime:int = 8;

		/*-----------UI界面-----------*/
		private var gameView:GameView;
		private var gameSettingView:GameSetting;
		private var gameOverView:GameOverView;

		//得分
		private var score:int;

		public function GameManager(){
			arrowList = [];
			targetList = [];
		}

		public static function getInstance() : GameManager
		{
			if(instance == null)
			{
				instance = new GameManager();
			}
			return instance;
		}

		private function init():void
		{
			//添加3D场景
			scene = new GameScene();
			Laya.stage.addChild(scene);
			
			//添加照相机
			camera = new GameCamera( 0, 0.1, 100);
			scene.addChild(camera);
			camera.transform.translate(new Vector3(0, 3, 3));
			//camera.transform.rotate(new Vector3( -30, 0, 0), true, false);

			//添加方向光
			var directionLight:DirectionLight = scene.addChild(new DirectionLight()) as DirectionLight;
			directionLight.color = new Vector3(0.6, 0.6, 0.6);
			directionLight.direction = new Vector3(0.1, -1, 0);
			//光照强度
			//directionLight.intensity = 0.6;

			//添加玩家
			player = new Player();
			camera.addChild(player);

			curTime = 0;
			Laya.timer.loop(1000,this,this.updateTarget);
		}

		public function loadRes():void
		{
			Laya.loader.create(["res/model/model.lh",
			"res/model/Assets/Skyboxes/Day_BlueSky_Nothing.ltc",
			"res/atlas/common.atlas"
			],Handler.create(this,this.loadCompleteHandler));
		}

		private function loadCompleteHandler():void
		{
			initCannon();
			init();
			initGameUI();
		}

		/**
		 * 初始化物理引擎
		 */
		private function initCannon():void
		{
			world = new CANNON.World();
			world.gravity.set(0, -9.8, 0);

			var groundShape = new CANNON.Plane();
			var groundBody = new CANNON.Body({
          		mass: 0
        	});
			groundBody.addShape(groundShape);
			world.addBody(groundBody);

			Laya.timer.frameLoop(1,this,this.loop);
		}

		/**
		 * 物理引擎计算
		 */
		private function loop():void
		{
			var nowTime:Number = TimerControlTool.now();
			if(lastTime != 0);
			{
				var dt:int = (nowTime - lastTime) / 1000;
				world.step(fixedTimeStep, dt, maxSubSteps);
			}
			lastTime = nowTime;
			updatePhysics();
			update();
		}

		/**
		 * 更新物体的运动位置
		 */
		private function update():void
		{
			var pos:Vector3 = new Vector3();
			for each(var item:Sprite3D in arrowList)
			{
				pos.x = item.rigidbody.position.x;
				pos.y = item.rigidbody.position.y;
				pos.z = item.rigidbody.position.z;
				item.transform.position = pos;
				if(pos.y < 0)
				{
					world.removeBody(item.rigidbody);
					scene.removeChild(item);
					var index:int = arrowList.indexOf(item);
					arrowList.splice(index,1);
				}
			}
		}

		private function updatePhysics():void
		{
			for each(var arrow:Sprite3D in arrowList)
			{
				ray.origin = arrow.transform.position;
				ray.direction = arrow.transform.right;
				Physics.rayCast(ray,outHitInfo,0.1,layerNum);
				if(outHitInfo.distance != -1)
				{
					//发生碰撞，直接删除箭跟目标
					//trace("碰撞" + outHitInfo.distance);
					var target:Target = outHitInfo.sprite3D as Target;
					if(target)
					{
						//移除目标
						scene.removeChild(target);
						var index:int = targetList.indexOf(target);
						targetList.splice(index,1);
						updateTargetNum();
						Target.returnTarget(target);
						//移除弓箭
						world.removeBody(arrow.rigidbody);
						scene.removeChild(arrow);
						var index:int = arrowList.indexOf(arrow);
						arrowList.splice(index,1);
						score += target.score;
						updateScore();
					}
				}
			}
		}

		/**
		 * 绑定到刚体
		 */
		private function bindRigidbody(runArrow:Sprite3D,velocity:Number):void
		{
			var radius = 1; // m
			var sphereBody = new CANNON.Body({
   				mass: 1, // kg
   				position: new CANNON.Vec3(runArrow.transform.position.x, runArrow.transform.position.y, runArrow.transform.position.z)
			});
			world.addBody(sphereBody);
			//需要计算角度修正
			var forward:Vector3 = new Vector3();
			var ray:Ray = new Ray(camera.position,camera.forward);
			var outHitInfo:RaycastHit = new RaycastHit();
			Physics.rayCast(ray,outHitInfo,MAX_DIS,layerNum);
			if(outHitInfo.distance != -1)
			{
				Vector3.subtract(outHitInfo.position, runArrow.transform.position, forward);
				Vector3.normalize(forward,forward);
			}
			else
			{
				var scaleVec:Vector3 = new Vector3();
				Vector3.scale(camera.forward,MAX_DIS,scaleVec);
				var targetPos:Vector3 = new Vector3();
				Vector3.add(camera.position,scaleVec,targetPos);
				Vector3.subtract(targetPos, runArrow.transform.position, forward);
				Vector3.normalize(forward,forward);
			}
			sphereBody.velocity = new CANNON.Vec3(forward.x * velocity,forward.y * velocity,forward.z * velocity);
			runArrow.rigidbody = sphereBody;
		}

		/**
		 * 添加弓箭到场景
		 */
		public function addArrow(runArrow:Sprite3D,velocity:Number):void
		{
			// var collider:BoxCollider = runArrow.addComponent(BoxCollider) as BoxCollider;
			// collider.setFromBoundBox(new BoundBox(new Vector3(0.0,-0.05,-0.04),new Vector3(1.37,0.02,0.04)));
			// runArrow.layer = Layer.getLayerByNumber(layerNum);
			scene.addChild(runArrow);
			bindRigidbody(runArrow,velocity);
			arrowList.push(runArrow);
		}

		/**
		 * 更新目标物刷新
		 */
		private function updateTarget():void
		{
			//随机几秒刷新
			if(randomTime == 0)
			{
				randomTime = Math.ceil(Math.random() * (refreshMaxTime - refreshMinTime) + refreshMinTime);
				randomCount = Math.ceil(Math.random() * 3);
				if(randomCount == 0)
					randomCount == 1;
			}
			if(curTime % randomTime == 0)
			{
				randomTime = 0;
				for(var i:int = 0;i<randomCount;i++)
				{
					randomRefreshOneTarget();
				}
			}
			curTime++;
		}

		/**
		 * 随机生成一个目标
		 */
		private function randomRefreshOneTarget():void
		{
			var random:int = Math.random()*100;
			var moveType:int;
			for(var i:int = 0;i<randomMoveArr.length;i++)
			{
				if(random <= randomMoveArr[i])
				{
					moveType = i + 1;
					break;
				}
			}
			var target:Target = Target.createTarget(Target.TYPE_1,moveType);
			var randomX:int = Math.random() * refreshRadius - refreshRadius / 2;
			var randomY:int = Math.random() * 10;
			var randomZ:int = Math.random() * refreshRadius - refreshRadius / 2;
			target.transform.position = new Vector3(randomX,randomY,randomZ);
			scene.addChild(target);
			target.layer = Layer.getLayerByNumber(layerNum);
			targetList.push(target);
			updateTargetNum();
			checkGameOver();
		}

		private function checkGameOver():void
		{
			if(targetList.length >= MAX_TARGET_NUM)
			{
				pauseGame();
				gameOverView ||= new GameOverView();
				gameOverView.setScore(score);
				Laya.stage.addChild(gameOverView);
			}
		}

		/**
		 * 暂停游戏
		 */
		public function pauseGame():void
		{
			Laya.timer.clear(this,this.updateTarget);
			Laya.timer.clear(this,this.loop);
			for each(var target:Target in targetList)
			{
				target.isPause = true;
			}
		}

		/**
		 * 继续游戏
		 */
		public function resumeGame():void
		{
			Laya.timer.loop(1000,this,this.updateTarget);
			Laya.timer.frameLoop(1,this,this.loop);
			for each(var target:Target in targetList)
			{
				target.isPause = false;
			}
		}

		/**
		 * 重新开始
		 */
		public function restartGame():void
		{
			for each(var target:Target in targetList)
			{
				scene.removeChild(target);
			}
			targetList = [];
			for each(var item:Sprite3D in arrowList)
			{
				world.removeBody(item.rigidbody);
				scene.removeChild(item);
			}
			arrowList = [];
			curTime = 0;
			score = 0;
			resumeGame();
			updateScore();
		}

		/**
		 * 初始化UI
		 */
		private  function initGameUI():void
		{
			gameView ||= new GameView();
			//摄像机绑定到摇杆
			gameView.bindCamera(camera);
			player.bindShotBtn(gameView.btn_shot);
			updateTargetNum();
			Laya.stage.addChild(gameView);
		}

		/**
		 * 更新剩余数量
		 */
		private function updateTargetNum():void
		{
			gameView.setCount(targetList.length);
		}

		/**
		 * 更新分数
		 */
		private function updateScore():void
		{
			if(gameView)
				gameView.setScore(score);
		}

		/**
		 * 打开设置界面
		 */
		public function openGameSetting():void
		{
			pauseGame();
			gameSettingView ||= new GameSetting();
			gameSettingView.popup();
		}

		public function closeGameSetting():void
		{
			resumeGame();
			if(gameSettingView)
				gameSettingView.close();
		}

		public function setLog(str:String):void
		{
			gameView.setLog(str);
		}
	}

}